﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Threading;
using System.Diagnostics;
using NPlot;

using PdfSharp.Viewing;

namespace NN
{
    public partial class MainWindow : Form
    {
        #region Member Declarations

        Thread bpThread;
        Thread genThread;
        backprop backPropAlg;
        GeneticAlgorithm theGenAlg;

        //delegate void ErrorPlotDelegate(int epoch, double err);
        delegate void ErrorPlotDelegate();
        delegate void FinishTrainingDelegate();
    
        public const int PLOTTING_INTERVAL = 10;  //define the interval at which to plot the error
        public int HiddenNodes { get; set; }
        public int HiddenLayers { get; set; }

        public List<string> theInputList;  //holds the input names
        public List<string> theOutputList; //holds the output names
        public List<List<double>> theInputDataList;  //contains the input data points [c, r]
        public List<List<double>> theOutputDataList; //contains the output data points [c, r]
        public List<double> inputLowerBoundsList=new List<double>();  //holds the minimum values for each input
        public List<double> inputUpperBoundsList = new List<double>();  //holds the maximum values for each input
        List<NPlot.Windows.PlotSurface2D> plotList;  //the list of plots (1 plot for every input

        public List<SimulationControl> ControlList;  

        public bool loadFromFile;  
        public bool networkInTraining;
        public bool trainingCompleted;
        public bool stopTraining;
        public bool inputsSplit;
        public bool IsLesioningEnabled { get; set; }
        public bool inputValidated { get; set; }

        public NPlot.Windows.PlotSurface2D errorPlot;
        public DataSet ds;
        private System.Windows.Forms.GroupBox BufferParameterGroupBox;
        public int trainingTime;        

        public List<Variable> theInputs;
        public List<Variable> theOutputs;
        public List<Variable> TrainingSet;        
        public List<Variable> ValidationSet;
        public InputParams InputParamsDialogBox;
        public OutputsDialog OutputsDialogBox;        
        private int numberOfInputs;
        private int numberOfOutputs;

        
        public double[][][] Weights;
        public double[][] Biases;
        public int[] Layers;
        public char ActivationFunction; //tanh or sigmiod;
        private bool importedWeights = false;

        private System.Windows.Forms.ToolStripMenuItem UsersManToolStripMenuItem;
        private System.Windows.Forms.ToolStripMenuItem AboutToolStripMenuItem;
        //private PdfSharp.Viewing.PdfAcroViewer theViewer;
        //private Form viewContainer;
        private PDFViewer theViewer;

        #endregion

        #region Initialization

        public MainWindow()
        {
            InitializeComponent();
            
            //TODO Serge temporarily disable unused widgets
            //button3.Visible = false;
            //label11.Visible = false;
            //progressBar1.Visible = true;
            groupBox3.Visible = false;
            //groupBox2.Visible = false;

            //initialize gui and network parameters
            InputParamsDialogBox = new InputParams();
            InputParamsDialogBox.setMainWindow(this);
            InputParamsDialogBox.Visible = false;
            trainingTime = 0;
            this.HiddenNodes = 22;
            this.HiddenLayers = 2;

            errorPlot = new NPlot.Windows.PlotSurface2D();
            this.errorPlot.Clear();
            this.errorPlot.AutoScaleAutoGeneratedAxes = false;
            this.errorPlot.AutoScaleTitle = false;
            this.errorPlot.BackColor = System.Drawing.SystemColors.ControlLightLight;            
            this.errorPlot.Legend = null;            
            this.errorPlot.Name = "errorPlot";
            this.errorPlot.RightMenu = null;
            this.errorPlot.ShowCoordinates = false;
            this.errorPlot.Location = new System.Drawing.Point(10, 20);
            this.errorPlot.Height = this.groupBox6.Height - 25;
            this.errorPlot.Width = this.groupBox6.Width - 20;            
            this.errorPlot.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
            this.errorPlot.TabIndex = 2;
            this.errorPlot.Title = "Error Plot";
            this.errorPlot.TitleFont = new System.Drawing.Font("Arial", 14F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Pixel);
            this.errorPlot.XAxis1 = null;
            this.errorPlot.XAxis2 = null;
            this.errorPlot.YAxis1 = null;
            this.errorPlot.YAxis2 = null;            
            this.groupBox6.Controls.Add(this.errorPlot);

            OutputsDialogBox = new OutputsDialog();
            OutputsDialogBox.setMainWindow(this);
            OutputsDialogBox.Visible = false;
            //add the invisible genetic alg parameters group box to the panel
            //do this in case designer overwrites my changes because its a piece of shit
            this.panel3.Controls.Add(this.groupBox10);
            this.groupBox9.Controls.Remove(this.groupBox10);
            this.groupBox10.Location = this.groupBox9.Location;
            this.groupBox10.Size = this.groupBox9.Size;
            
            this.outputsToolStripMenuItem.Click += new System.EventHandler(this.outputsToolStripMenuItem_Click);
            this.dataGridInputColumnList = new List<DataGridViewTextBoxColumn>();
            this.dataGridOutputColumnList = new List<DataGridViewTextBoxColumn>();
            dataGridOutputColumnList.Add(this.dataGridViewTextBoxColumn2);
            dataGridInputColumnList.Add(this.Input);
            this.dataGridView1.RowsAdded += new DataGridViewRowsAddedEventHandler(this.syncIORowsAdded);
            this.dataGridView2.RowsAdded += new DataGridViewRowsAddedEventHandler(this.syncIORowsAdded);            
            this.dataGridView2.UserDeletingRow += new DataGridViewRowCancelEventHandler(dataGridView2_UserDeletingRow);
            this.dataGridView1.UserDeletingRow += new DataGridViewRowCancelEventHandler(dataGridView1_UserDeletingRow);
            theInputList = new List<string>();
            theOutputList = new List<string>();
            theInputDataList = new List<List<double>>();
            theOutputDataList = new List<List<double>>();            
            theInputs = new List<Variable>();
            theOutputs = new List<Variable>();
            plotList = new List<NPlot.Windows.PlotSurface2D>();
            inputLowerBoundsList = new List<double>();
            inputUpperBoundsList = new List<double>();
            TrainingSet = new List<Variable>();
            ValidationSet = new List<Variable>();

            loadFromFile = false;
            this.inputValidated = false;
            stopTraining = false;
            networkInTraining = false;
            BufferParameterGroupBox = this.groupBox9;
            trainingCompleted = false;
            inputsSplit = false;
            
            TrainingMethodComboBox.SelectedIndex = 0;
            comboBox2.SelectedIndex = 0;
            comboBox3.SelectedIndex = 0;

            //help menu items
            this.AboutToolStripMenuItem = new ToolStripMenuItem();
            this.AboutToolStripMenuItem.Text = "About...";
            this.helpToolStripMenuItem.DropDownItems.Add(this.AboutToolStripMenuItem);
            this.AboutToolStripMenuItem.Click += new EventHandler(AboutToolStripMenuItem_Click);
            this.UsersManToolStripMenuItem = new ToolStripMenuItem();            
            this.UsersManToolStripMenuItem.Text = "Users Manual";
            this.helpToolStripMenuItem.DropDownItems.Add(this.UsersManToolStripMenuItem);
            this.UsersManToolStripMenuItem.Click += new EventHandler(UsersManToolStripMenuItem_Click);

            theViewer = new PDFViewer();
            theViewer.FormClosing += new FormClosingEventHandler(theViewer_FormClosing);

            //initialize menu strip
            this.menuStrip1.Items.Add(File);
            this.menuStrip1.Items.Add(dataToolStripMenuItem);
            this.menuStrip1.Items.Add(toolsToolStripMenuItem);
            this.menuStrip1.Items.Add(helpToolStripMenuItem);
            this.menuStrip1.Show();
            this.newToolStripMenuItem.Click += new EventHandler(newToolStripMenuItem_Click);
            this.exitToolStripMenuItem.Click += new EventHandler(exitToolStripMenuItem_Click);
            this.saveToolStripMenuItem.Dispose();
            this.loadToolStripMenuItem.Click += this.button1_Click;
            this.plottingToolStripMenuItem.Enabled = false;
            this.trainingSummaryToolStripMenuItem.Enabled = false;
            this.simulationToolStripMenuItem.Enabled = false;
            this.plottingToolStripMenuItem.Click += new EventHandler(plottingToolStripMenuItem_Click);
            this.simulationToolStripMenuItem.Click += new EventHandler(simulationToolStripMenuItem_Click);
            this.TabControl.Selecting += new TabControlCancelEventHandler(TabControl_Selecting);
            this.FormClosing += new FormClosingEventHandler(MainWindow_FormClosing);            
        }

        void theViewer_FormClosing(object sender, FormClosingEventArgs e)
        {
            theViewer.resources.ReleaseAllResources();
            //theViewer.Dispose();
        }

        void AboutToolStripMenuItem_Click(object sender, EventArgs e)
        {            
            /*if (theViewer != null)
            {
                theViewer.Dispose();
                //theViewer.Close();
                theViewer = null;
            }*/
            theViewer = new PDFViewer();
            theViewer.Title = "About...";
            theViewer.SetTitle();
            theViewer.LoadPDF("About.pdf");
        }

        void UsersManToolStripMenuItem_Click(object sender, EventArgs e)
        {
            /*if (theViewer != null)
            {
                theViewer.Dispose();
                //theViewer.Close();
                theViewer = null;
            }*/
            theViewer = new PDFViewer();
            theViewer.Title = "Users Manual ICE v2.0";
            theViewer.SetTitle();
            theViewer.LoadPDF("ICE2.0_Help.pdf");
        }

        void MainWindow_FormClosing(object sender, FormClosingEventArgs e)
        {
            /*for (int i = 0; i < Application.OpenForms.Count; i++)
            {
                Application.OpenForms[i].Close();
            }*/
            Application.ExitThread();
        }

        void simulationToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (trainingCompleted)
            {
                TabControl.SelectTab(4);
            }
        }

        void TabControl_Selecting(object sender, TabControlCancelEventArgs e)
        {            
            int newTabIndex = e.TabPageIndex;
            int currTabIndex = TabControl.SelectedIndex;
            
            switch (newTabIndex)
            {
                case 0:
                    if (!networkInTraining)
                    {
                        break;
                    }
                    else
                    {
                        e.Cancel = true;
                    }
                    break;
                case 1:
                    if (inputValidated)
                    {
                        break;
                    }
                    else
                    {
                        if (numericUpDown1.Value > 0 && numericUpDown2.Value > 0)
                        {
                            this.validateInputData();
                            this.storeInputData();
                            if (this.inputValidated)
                            {
                                //splitInputs();
                                TabControl.SelectTab(1);
                            }
                        }
                        else
                        {
                            MessageBox.Show("No inputs/outputs found! Please check the input data");
                        }                        
                        e.Cancel = true;
                        break;
                    }
                case 2:
                    if (trainingCompleted)
                    {
                        break;
                    }
                    else
                    {
                        MessageBox.Show("The summary results are not available until a network is trained");
                        e.Cancel = true;
                        break;
                    }
                case 3:
                    if (trainingCompleted)
                    {
                        break;
                    }
                    else
                    {
                        MessageBox.Show("No plots are available until a network is trained.");
                        e.Cancel = true;
                        break;
                    }
                case 4:
                    if (trainingCompleted)
                    {
                        break;
                    }
                    else
                    {
                        //MessageBox.Show("A network must be trained before it becomes on-line");
                        //e.Cancel = true;
                        break;
                    }
                default:
                    break;
            }
        }       

        void plottingToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (trainingCompleted)
            {
                this.TabControl.SelectTab(3);
            }
        }

        void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Application.ExitThread();
        }

        void newToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Application.Restart();
            //throw new NotImplementedException();
        }

        #endregion

        #region Input Data Functions

        private void syncIORowsAdded(Object sender, EventArgs e)
        {
            int view1Rows, view2Rows;
            view1Rows = this.dataGridView1.RowCount;
            view2Rows = this.dataGridView2.RowCount;
            if (view1Rows > view2Rows)
            {
                this.dataGridView2.RowCount = view1Rows;
            }
            if (view2Rows > view1Rows)
            {
                this.dataGridView1.RowCount = view2Rows;
            }
        }
        private void resetData()
        {
            this.dataGridInputColumnList.Clear();
            this.dataGridInputColumnList.Add(this.Input);
            this.dataGridOutputColumnList.Clear();
            this.dataGridOutputColumnList.Add(this.dataGridViewTextBoxColumn2);
            this.dataGridView1.Columns.Clear();
            this.dataGridView1.Columns.Add(this.Input);
            this.dataGridView2.Columns.Clear();
            this.dataGridView2.Columns.Add(this.dataGridViewTextBoxColumn2);
            this.dataGridView1.Rows.Clear();
            this.dataGridView2.Rows.Clear();
            dataGridView1.RowCount = 1;
            dataGridView2.RowCount = 1;
            for (int i = 0; i < dataGridView1.Rows.Count-1; i++)
            {
                dataGridView1.Rows.RemoveAt(i);
            }
            for (int i = 0; i < dataGridView1.Rows.Count - 1; i++)
            {
                dataGridView2.Rows.RemoveAt(i);
            }


            theInputList.Clear();
            theOutputList.Clear();
            theInputDataList.Clear();
            theOutputDataList.Clear();
            theInputs.Clear();
            theOutputs.Clear();
            inputLowerBoundsList.Clear();
            inputUpperBoundsList.Clear();
            TrainingSet.Clear();
            ValidationSet.Clear();
            plotList.Clear();
            comboBox4.Items.Clear();
        }       

        private void numericUpDown1_ValueChanged(object sender, EventArgs e)
        {
            if (!loadFromFile)
            {
                decimal numInputs;
                DataGridViewTextBoxColumn temp = new DataGridViewTextBoxColumn();
                numInputs = numericUpDown1.Value;
                numberOfInputs = (int)numInputs;

                if (this.dataGridInputColumnList.Count < numInputs)
                {
                    temp.Name = "Inputs";
                    temp.HeaderText = "Input " + numInputs.ToString();
                    temp.Width = 80;
                    dataGridView1.Columns.Add(temp);
                    this.dataGridInputColumnList.Add(temp);
                    theInputList.Add(temp.HeaderText);
                }
                else
                {
                    if (numInputs >= 0)
                    {
                        dataGridView1.Columns.Remove(this.dataGridInputColumnList.ElementAt(dataGridInputColumnList.Count - 1));
                        this.dataGridInputColumnList.Remove(this.dataGridInputColumnList.ElementAt(dataGridInputColumnList.Count - 1));
                    }

                }
            }
            else
            {
                numericUpDown1.Value = theInputList.Count;
            }



        }

        private void numericUpDown2_ValueChanged(object sender, EventArgs e)
        {
            if (!loadFromFile)
            {
                decimal numOutputs;
                DataGridViewTextBoxColumn temp = new DataGridViewTextBoxColumn();
                numOutputs = numericUpDown2.Value;
                numberOfOutputs = (int)numOutputs;

                if (this.dataGridOutputColumnList.Count < numOutputs)
                {
                    temp.Name = "Outputs";
                    temp.HeaderText = "Output " + numOutputs.ToString();
                    temp.Width = 80;
                    dataGridView2.Columns.Add(temp);
                    theOutputList.Add(temp.HeaderText);
                    this.dataGridOutputColumnList.Add(temp);
                }
                else
                {
                    //dataGridView1.Columns.RemoveAt(dataGridView1.Columns.Count - 1);
                    if (numOutputs >= 0)
                    {
                        dataGridView2.Columns.Remove(this.dataGridOutputColumnList.ElementAt(dataGridOutputColumnList.Count - 1));
                        this.dataGridOutputColumnList.Remove(this.dataGridOutputColumnList.ElementAt(dataGridOutputColumnList.Count - 1));
                    }

                }
            }
            else
            {
                numericUpDown2.Value = theOutputList.Count;
            }
        }       

        private void button1_Click(object sender, EventArgs e)
        {
            openFileDialog1.ShowDialog();
        }

        private void openFileDialog1_FileOk(object sender, CancelEventArgs e)
        {            
            textBox1.Text = openFileDialog1.SafeFileName;
            StreamReader file = new StreamReader(openFileDialog1.FileName);
            string firstLine, temp;
            string inputName = null;
            string outputName = null;            
            //int indexInputColon = 0, indexInputSpace = 0;
            //int indexOutputColon = 0, indexOutputSpace = 0;
            int inputsCount = 0, outputsCount = 0;
            int rowNum = 0;
            List<string> parsedLineValues = new List<string>();
            List<List<string>> theInputs = new List<List<string>>();
            List<List<string>> theOutputs = new List<List<string>>();
            List<string> splitInputs = new List<string>();
            List<string> splitOutputs = new List<string>();
            bool parseSuceeded = true;


            //TODO validate file extension (we only accept .csv,  .txt)
            loadFromFile = true;
            //reset and clear all current inputs/outputs
            this.resetData();
            inputsSplit = false;

            //the first line will define the inputs and outputs            
            firstLine = file.ReadLine();
            temp = firstLine;
            
            //parse first line to find number of inputs, outputs

            /*
            while(indexInputColon >= 0)
            {
                if (indexInputSpace >= 0)
                {
                    indexInputColon = firstLine.IndexOf("in:", indexInputSpace);                    
                }
                if (indexOutputSpace >= 0)
                {
                    indexOutputColon = firstLine.IndexOf("out:", indexOutputSpace);
                }
                
                if (indexInputColon >= 0)
                {
                    indexInputSpace = firstLine.IndexOf(' ', indexInputColon);                    
                }
                if(indexOutputColon >= 0)
                {
                    indexOutputSpace = firstLine.IndexOf(' ', indexOutputColon);
                }
                
                if (indexInputColon >= 0 && indexInputSpace - 3 >= 0 && indexInputSpace - 1 < temp.Length)
                {
                    inputName = temp.Substring(indexInputColon + 3, (indexInputSpace - 3 - indexInputColon));                    
                }
                if (indexOutputColon >= 0 && indexOutputSpace - 4 >= 0 && indexOutputSpace - 1 < temp.Length)
                {
                    outputName = temp.Substring(indexOutputColon + 4, (indexOutputSpace - 4 - indexOutputColon));                    
                    
                }
              */ 
            char[] delimiters= {' ','\t',',',':'};
            
            string[] tempLine = firstLine.Split(delimiters);
            for (int i = 0; i < tempLine.Length; i++)
            {
                if(tempLine[i].Equals("in"))
                {
                    i++;
                    theInputList.Add(tempLine[i]);
                    inputName = tempLine[i];
                }
                if (tempLine[i].Equals("out"))
                {
                    i++;
                    theOutputList.Add(tempLine[i]);
                    outputName = tempLine[i];
                }
                if (theInputList.Count >= dataGridInputColumnList.Count && inputName != null)
                {
                    DataGridViewTextBoxColumn tempCol = new DataGridViewTextBoxColumn();
                    tempCol.Name = inputName;
                    tempCol.HeaderText = inputName;
                    tempCol.Width = 80;
                    if (dataGridInputColumnList.ElementAt(0) == this.Input)
                    {
                        dataGridInputColumnList.RemoveAt(0);
                        dataGridInputColumnList.Add(tempCol);
                        dataGridView1.Columns.Insert(0, tempCol);
                        dataGridView1.Columns.RemoveAt(1);
                    }
                    else
                    {
                        dataGridInputColumnList.Add(tempCol);
                        this.dataGridView1.Columns.Add(tempCol);
                    }
                }
                if (theOutputList.Count >= dataGridOutputColumnList.Count && outputName != null)
                {
                    DataGridViewTextBoxColumn tempCol2 = new DataGridViewTextBoxColumn();
                    tempCol2.Name = outputName;
                    tempCol2.HeaderText = outputName;
                    tempCol2.Width = 80;
                    if (dataGridOutputColumnList.ElementAt(0) == this.dataGridViewTextBoxColumn2)
                    {
                        dataGridOutputColumnList.RemoveAt(0);
                        dataGridOutputColumnList.Add(tempCol2);
                        dataGridView2.Columns.Insert(0, tempCol2);
                        dataGridView2.Columns.RemoveAt(1);
                    }
                    else
                    {
                        dataGridOutputColumnList.Add(tempCol2);
                        this.dataGridView2.Columns.Add(tempCol2);
                    }
                }
                inputName = null;
                outputName = null;
            }
            
                
            //}
            //read and parse rest of input/output values                        
            inputsCount = theInputList.Count;
            outputsCount = theOutputList.Count;
            numericUpDown1.Value = inputsCount;
            numericUpDown2.Value = outputsCount;           

            //loop through data file line by line
            while (!file.EndOfStream)
            {
                splitInputs.Clear();
                splitOutputs.Clear();
                
                parsedLineValues = this.parseLine(file);
                
                if (parsedLineValues.Count == inputsCount + outputsCount)
                {
                    dataGridView1.RowCount++;
                    for (int x = 0; x < inputsCount; x++)
                    {
                        splitInputs.Add(parsedLineValues.ElementAt(x));
                    }
                    for (int y = inputsCount; y < parsedLineValues.Count; y++)
                    {
                        splitOutputs.Add(parsedLineValues.ElementAt(y));
                    }

                    for(int x = 0; x< inputsCount; x++)
                    {                       
                        dataGridView1.CurrentCell = this.dataGridView1[x, rowNum];
                        dataGridView1.CurrentCell.ReadOnly = false;                        
                        dataGridView1.CurrentCell.Value = splitInputs.ElementAt(x);                        
                        dataGridView1.UpdateCellValue(x, rowNum);
                        dataGridView1.CurrentCell.ReadOnly = true;
                    }
                    
                    for (int y = 0; y < outputsCount; y++)
                    {
                        
                        dataGridView2.CurrentCell = this.dataGridView2[y, rowNum];
                        dataGridView2.CurrentCell.ReadOnly = false;                        
                        dataGridView2.CurrentCell.Value = splitOutputs.ElementAt(y);
                        dataGridView2.UpdateCellValue(y, rowNum);
                        dataGridView2.CurrentCell.ReadOnly = true;
                    }
                   
                    rowNum++;
                }
                else if (parsedLineValues.Count == 0)
                {
                }
                else
                {
                    parseSuceeded = false;
                    MessageBox.Show("There was an error parsing the file " + openFileDialog1.FileName + ". Please restart the application and try again.");
                }
            }

            if (parseSuceeded)
            {
                //populate the inputs in the inputs parameters dialog box
                this.storeInputData();
                this.InputParamsDialogBox.setInputs(dataGridView1);
                this.OutputsDialogBox.setInputs(dataGridView2);
            }

            file.Close();
        }

        List<string> parseLine(StreamReader file)
        {
            string value = "", line;            
            List<string> valuesList = new List<string>();
            bool valAdded = false;

            char[] delimiters= {' ','\t',','};

            //parse one line at a time
            line = file.ReadLine();

            string[] values = line.Split(delimiters);
            for (int i = 0; i < values.Length; i++)
            {
                if (!values[i].Equals(""))
                {
                    valuesList.Add(values[i]);
                }
            }

            /*
            line = file.ReadLine();
            for (int a = 0; a < line.Length; a++)
            {
                if (!char.IsWhiteSpace(line, a))
                {
                    value += line.Substring(a, 1);
                    valAdded = false;
                }
                else
                {
                    valuesList.Add(value);
                    value = "";
                    valAdded = true;
                }
            }
            //add last value to the list
            if (!valAdded)
            {
                valuesList.Add(value);
            }
            */
            return valuesList;
        }
                
        private void storeInputData()
        {            
            List<double> tempInputList;
            List<double> tempOutputList;            
            double cellVal;
            int numPoints = dataGridView1.Rows.Count - 1;

            //in case this function is called twice, clear the lists...
            theInputs.Clear();
            theOutputs.Clear();
            theInputDataList.Clear();
            theOutputDataList.Clear();
            theInputList.Clear();
            theOutputList.Clear();

            for (int c = 0; c < dataGridView1.Columns.Count; c++)
            {                
                tempInputList = new List<double>();
                tempInputList.Clear();
                theInputList.Add(dataGridView1.Columns[c].HeaderText);

                for (int r = 0; r < dataGridView1.Rows.Count - 1; r++)
                {
                    dataGridView1.CurrentCell = dataGridView1[c, r];
                    if (dataGridView1.CurrentCell.Value != null)
                    {
                        if (dataGridView1.CurrentCell.Value.ToString().Length > 0)
                        {
                            cellVal = double.Parse((String)dataGridView1.CurrentCell.Value.ToString());
                            tempInputList.Add(cellVal);
                        }
                    }
                    
                }
                if (tempInputList.Count < numPoints)
                {
                    MessageBox.Show("Warning! The inputs were not set properly, the network may not train properly");
                }
                theInputDataList.Add(tempInputList);
            }

            for (int c = 0; c < dataGridView2.Columns.Count; c++)
            {
                tempOutputList = new List<double>();
                tempOutputList.Clear();
                theOutputList.Add(dataGridView2.Columns[c].HeaderText);
                for (int r = 0; r < dataGridView2.Rows.Count - 1; r++)
                {
                    dataGridView2.CurrentCell = dataGridView2[c, r];
                    if (dataGridView2.CurrentCell.Value != null)
                    {
                        if (dataGridView2.CurrentCell.Value.ToString().Length > 0)
                        {
                            cellVal = double.Parse((String)dataGridView2.CurrentCell.Value.ToString());
                            tempOutputList.Add(cellVal);
                        }
                    }
                }
                if (tempOutputList.Count < numPoints)
                {
                    MessageBox.Show("Warning! The outputs were not set properly, the network may not train properly");
                }
                theOutputDataList.Add(tempOutputList);
            }           
            
            /////////////////////////////////////////////////////////////////////////////////
            //populate the data to be used by the training algorithm
            /////////////////////////////////////////////////////////////////////////////////
            for (int i = 0; i < theInputDataList.Count; i++)
            {
                Variable tempInput = new Variable();
                tempInput.VariableName = theInputList.ElementAt(i);
                tempInput.Type = "Independent";
                tempInput.SetData(theInputDataList.ElementAt(i));
                /*for (int j = 0; j < theInputDataList.ElementAt(i).Count; j++)
                {
                    tempInput.Add(theInputDataList.ElementAt(i).ElementAt(j));
                }*/
                tempInput.calculateRange();
                theInputs.Add(tempInput);
            }

            for (int i = 0; i < theOutputDataList.Count; i++)
            {
                Variable tempOutput = new Variable();
                tempOutput.VariableName = theOutputList.ElementAt(i);
                tempOutput.Type = "Dependent";
                tempOutput.SetData(theOutputDataList.ElementAt(i));
                /*for (int j = 0; j < theOutputDataList.ElementAt(i).Count; j++)
                {
                    tempOutput.Add(theOutputDataList.ElementAt(i).ElementAt(j));
                }*/
                tempOutput.calculateRange();
                theOutputs.Add(tempOutput);
            }

        }

        private void validateInputData()
        {
            double cellValue;
            
            //verify that the inputs and desired outputs are valid real, rational numbers
            if (dataGridView1.Rows.Count > 2 && dataGridView2.Rows.Count > 2)
            {
                if (dataGridView1.Rows.Count == dataGridView2.Rows.Count)
                {
                    for (int c = 0; c < dataGridView1.ColumnCount; c++)
                    {
                        for (int r = 0; r < dataGridView1.Rows.Count; r++)
                        {
                            dataGridView1.CurrentCell = dataGridView1[c, r];
                            if (dataGridView1.CurrentCell.Value == null)
                            {                                
                                //dataGridView1.Rows.RemoveAt(dataGridView1.CurrentCell.RowIndex);
                            }
                            else
                            {
                                if (double.TryParse((String)dataGridView1.CurrentCell.Value, out cellValue))
                                {
                                    inputValidated = true;
                                }
                                else
                                {
                                    MessageBox.Show("Please make sure all data points are real, rational numbers");
                                    inputValidated = false;
                                }
                            }
                        }
                    }

                    for (int c = 0; c < dataGridView2.ColumnCount; c++)
                    {
                        for (int r = 0; r < dataGridView2.Rows.Count; r++)
                        {
                            dataGridView2.CurrentCell = dataGridView2[c, r];
                            if (dataGridView2.CurrentCell.Value == null)
                            {                                
                                //dataGridView2.Rows.RemoveAt(dataGridView2.CurrentCell.RowIndex);
                            }
                            else
                            {
                                if (double.TryParse((String)dataGridView2.CurrentCell.Value, out cellValue))
                                {
                                    inputValidated = true;
                                }
                                else
                                {
                                    MessageBox.Show("Please make sure all data points are real, rational numbers");                                    
                                    inputValidated = false;
                                }
                            }
                        }
                    }
                    
                }
                else
                {
                    //prune inputs or outputs if there is a mismatch in row count
                    if (dataGridView1.Rows.Count > dataGridView2.Rows.Count)
                    {
                        dataGridView1.Rows.RemoveAt(dataGridView1.Rows.Count - 1);
                        this.validateInputData();
                    }
                    else
                    {
                        dataGridView2.Rows.RemoveAt(dataGridView2.Rows.Count - 1);
                        this.validateInputData();
                    }
                }
            }
            else
            {
                inputValidated = false;
                MessageBox.Show("There are not enough input data points to train the network! Please add more data points");
            }
            
        }

        #endregion

        #region Training Functions

        private void TrainingButtonCNPage_Click(object sender, EventArgs e)
        {            
            /*double err = 0;            
            int epoch = 0;            
            double solutionQuality = 0;
            double aam = 0;
            double avgErr = 0;*/
            ds = new DataSet("Error");
            Object[] point = new Object[2];
            int[] layers;  //holds the dimensions of the network (nodes per layer)
            double[,] trainingInputs;
            double[,] trainingOutputs;
            double[,] validationInputs;
            double[,] validationOutputs;
            bool dontSplitInputs = false;

            if (theInputs[0].PointCount() > 10)
            {
                dontSplitInputs = false;
                if (!this.inputsSplit)
                {
                    splitInputs();
                }

                if (inputsSplit)
                {
                    trainingInputs = new double[TrainingSet.ElementAt(0).PointCount(), theInputs.Count];
                    trainingOutputs = new double[TrainingSet.ElementAt(0).PointCount(), theOutputs.Count];
                    validationInputs = new double[ValidationSet.ElementAt(0).PointCount(), theInputs.Count];
                    validationOutputs = new double[ValidationSet.ElementAt(0).PointCount(), theOutputs.Count];
                }
                else
                {
                    //if theres an error splitting the inputs, abort training process
                    return;
                }
            }
            else
            {
                dontSplitInputs = true;
                trainingInputs = new double[theInputs[0].PointCount(), theInputs.Count];
                trainingOutputs = new double[theInputs[0].PointCount(), theOutputs.Count];
                //validationInputs = new double[theInputs[0].PointCount(), theInputs.Count];
                //validationOutputs = new double[theInputs[0].PointCount(), theOutputs.Count];
                validationInputs = null;
                validationOutputs = null;
            }
            //if a previous thread exists, kill it
            if(bpThread != null)
            {
                if (backPropAlg != null)
                {
                    backPropAlg.abortTraining();
                }
                bpThread.Abort();
                bpThread = null;
            }

            if (genThread != null)
            {
                if (theGenAlg != null)
                {
                    theGenAlg.abortTraining();
                }
                genThread.Abort();
                genThread = null;
            }

            //set the network structure based on the selected training alg
            if (TrainingMethodComboBox.SelectedIndex == 0)
            {
                HiddenNodes = int.Parse(this.textBox10.Text);
                HiddenLayers = (int)this.numericUpDown4.Value;
            }
            else
            {
                HiddenNodes = int.Parse(this.textBox11.Text);
                HiddenLayers = (int)this.numericUpDown5.Value;
            }
            if (HiddenNodes <= 0)
            {
                MessageBox.Show("The network cannot have layers with " + HiddenNodes.ToString() + " nodes.");
                return;
            }


            layers = new int[HiddenLayers + 2];
            layers[0] = theInputs.Count;
            networkInTraining = true;
            this.button3.Enabled = true;
            this.inputsToolStripMenuItem.Enabled = false;
            this.outputsToolStripMenuItem.Enabled = false;
            this.loadToolStripMenuItem.Enabled = false;
            this.IsLesioningEnabled = this.checkBox1.Checked;
            
            //initialize the error plot            
            ds.Tables.Add();
            ds.Tables[0].Columns.Add();
            ds.Tables[0].Columns[0].DataType = System.Type.GetType("System.Int32");
            ds.Tables[0].Columns[0].ColumnName = "Epochs";
            ds.Tables[0].Columns.Add();
            ds.Tables[0].Columns[1].DataType = System.Type.GetType("System.Double");
            
            if (this.TrainingMethodComboBox.SelectedIndex == 0)
            {
                ds.Tables[0].Columns[1].ColumnName = "Error";                
            }
            else
            {
                ds.Tables[0].Columns[1].ColumnName = "Fitness";                
            }

            this.UpdateErrorPlot(ds);
            errorPlot.YAxis1.LabelOffsetAbsolute = true;
            errorPlot.YAxis1.LabelOffset = 40;
            errorPlot.Padding = 1;            
            errorPlot.AddAxesConstraint(new AxesConstraint.AxisPosition(PlotSurface2D.YAxisPosition.Left, 60));

            //determine the initial structure of the network (number of nodes in each layer)
            for (int i = 1; i < layers.Count() - 1; i++)
            {
                layers[i] = HiddenNodes;
            }

            layers[layers.Count() - 1] = theOutputs.Count;
            Layers = layers;
            
            //package the inputs and outputs into array for backprop            
            for (int i = 0; i < theInputs.Count; i++)
            {
                if (dontSplitInputs)
                {
                    for (int j = 0; j < theInputs.ElementAt(0).PointCount(); j++)
                    {
                        trainingInputs[j, i] = theInputs.ElementAt(i).GetPoints().ElementAt(j);
                    }
                }
                else
                {
                    for (int j = 0; j < TrainingSet.ElementAt(0).PointCount(); j++)
                    {
                        trainingInputs[j, i] = TrainingSet.ElementAt(i).GetPoints().ElementAt(j);
                    }
                }
            }
            for (int i = 0; i < theOutputs.Count; i++)
            {
                if (dontSplitInputs)
                {
                    for (int j = 0; j < theOutputs.ElementAt(0).PointCount(); j++)
                    {
                        trainingOutputs[j, i] = theOutputs.ElementAt(i).GetPoints().ElementAt(j);
                    }
                }
                else
                {
                    for (int j = 0; j < TrainingSet.ElementAt(0).PointCount(); j++)
                    {
                        trainingOutputs[j, i] = TrainingSet.ElementAt(i + theInputs.Count).GetPoints().ElementAt(j);
                    }
                }
            }

            //package inputs and outputs into arrays used for validation testing
            if (!dontSplitInputs)
            {
                for (int i = 0; i < theInputs.Count; i++)
                {
                    for (int j = 0; j < ValidationSet.ElementAt(0).PointCount(); j++)
                    {
                        validationInputs[j, i] = ValidationSet.ElementAt(i).GetPoints().ElementAt(j);
                    }
                }
                for (int i = 0; i < theOutputs.Count; i++)
                {
                    for (int j = 0; j < ValidationSet.ElementAt(0).PointCount(); j++)
                    {
                        validationOutputs[j, i] = ValidationSet.ElementAt(i + theInputs.Count).GetPoints().ElementAt(j);
                    }
                }
            }                       

            //////////////////////////////////////////////////////////////////////////////
            //perform back prop training
            if (this.TrainingMethodComboBox.SelectedIndex == 0)
            {                
                double userLearningRate, userConvergenceParameter;
                userLearningRate = double.Parse(this.LearningRateTextBox.Text);
                userConvergenceParameter = double.Parse(this.convergenceParameterTextBox.Text);
                
                if (IsLesioningEnabled && theInputs.Count < 2)
                {
                    MessageBox.Show("Error: Need multiple inputs to lesion");
                    checkBox1.Checked = false;
                    networkInTraining = false;
                    return;
                }

                //determine activation function to use during training
                if (comboBox2.SelectedIndex == 0)
                {
                    ActivationFunction = 't';
                }
                else
                {
                    ActivationFunction = 's';
                }

                //can't have a negative learning rate
                if (userLearningRate <= 0.0)
                {
                    this.button3.Enabled = false;
                    networkInTraining = false;
                    MessageBox.Show("Error: The learning rate must be a positive number!");
                    return;
                }else if(userLearningRate >= 1.0)
                {
                    this.button3.Enabled = false;
                    networkInTraining = false;
                    MessageBox.Show("Error: The learning rate must be less than 1.0!");
                    return;
                }
                

                // test validation and training parameters - doesn't work
                int blah = int.Parse(textBox13.Text) + int.Parse(textBox12.Text);
                if ( blah != 100 )
                {
                    this.button3.Enabled = false;
                    networkInTraining = false;
                    MessageBox.Show("Error: Training and validation percentages must sum to 100!!!");
                    return;
                }

                // test convergence parameter
                if (userConvergenceParameter <= 0.0)
                {
                    this.button3.Enabled = false;
                    networkInTraining = false;
                    MessageBox.Show("Error: The convergence parameter must be a positive number!");
                    return;
                }

                backPropAlg = new backprop(layers, trainingInputs, trainingOutputs, validationInputs, validationOutputs, '1', userConvergenceParameter, IsLesioningEnabled);
                button7.Enabled = false;                
                backPropAlg.nnFunction = ActivationFunction;
                backPropAlg.learningRate = userLearningRate;

                backPropAlg.ParentWindow = (MainWindow)this;

                if (importedWeights)
                {
                    backPropAlg.SetLayers(Layers);
                    backPropAlg.SetWeights(Weights);
                    backPropAlg.SetBiases(Biases);
                }
                importedWeights = false;

                bpThread = new Thread(new ThreadStart(backPropAlg.runBP));
                bpThread.Start();                                     
            }

            //////////////////////////////////////////////////////////////////////////////
            //Train using genetic algorithm
            if (this.TrainingMethodComboBox.SelectedIndex == 1)
            {                
                double mutationRate = double.Parse(textBox14.Text);
                int populationSize = int.Parse(textBox15.Text);
                double convergenceParameter = double.Parse(textBox5.Text);

                if (mutationRate <= 0 || mutationRate >= 1.0)
                {
                    this.button3.Enabled = false;
                    networkInTraining = false;
                    MessageBox.Show("The mutation rate must be within the range [0, 1]");
                    return;
                }

                if (populationSize < 1)
                {
                    this.button3.Enabled = false;
                    networkInTraining = false;
                    MessageBox.Show("The population must be non-zero, please enter a valid size");
                    return;
                }

                //determine activation function to use during training
                if (comboBox3.SelectedIndex == 0)
                {
                    ActivationFunction = 't';
                }
                else
                {
                    ActivationFunction = 's';
                }

                if (convergenceParameter <= 0.0)
                {
                    this.button3.Enabled = false;
                    networkInTraining = false;
                    MessageBox.Show("Error: The convergence parameter must be a positive number!");
                    return;
                }

                theGenAlg = new GeneticAlgorithm(populationSize, mutationRate, layers, trainingInputs, trainingOutputs, validationInputs, validationOutputs, '1', convergenceParameter);
                button7.Enabled = false;
                theGenAlg.nnFunction = ActivationFunction;
                theGenAlg.mu = mutationRate;
                theGenAlg.popSize = populationSize;

                theGenAlg.ParentWindow = (MainWindow)this;
                
                if (importedWeights)
                {
                    theGenAlg.SetLayers(Layers);
                    theGenAlg.SetWeights(Weights);
                    theGenAlg.SetBiases(Biases);
                }
                importedWeights = false;
                
                genThread = new Thread(new ThreadStart(theGenAlg.runGA));                
                genThread.Start();
            }           
        }
        
        public void EndBackProp()
        {
            if (InvokeRequired)
            {
                //call BeginInvoke if we are not in the UI thread                
                BeginInvoke(new FinishTrainingDelegate(EndBackProp), null);
                return;
            }

            double solutionQuality = 0;
            int epoch = backPropAlg.GetElapsedEpochs();
            double aam = 0;
            double avgErr = 0;
            double lesionTestedInputs = 0;
            double lesionIterVal = 0;
            double lesionTime = 0;
            double lesionInput = 0;
            double lesionError = 0;
            double lesionAAM = 0;
            double lesionCorr = 0;

            this.button3.Enabled = false;            
            this.button7.Enabled = true;
            this.inputsToolStripMenuItem.Enabled = true;
            this.outputsToolStripMenuItem.Enabled = true;
            this.loadToolStripMenuItem.Enabled = true;
            networkInTraining = false;

            if (epoch > 0)
            {
                solutionQuality = backPropAlg.correlation[epoch - 1];
                aam = backPropAlg.aam[epoch - 1];
                avgErr = backPropAlg.error[epoch - 1] / theInputs[0].PointCount();
                if (IsLesioningEnabled)
                {
                    lesionIterVal = epoch * theInputs.Count;
                    lesionTime = backPropAlg.lesionTime;
                    lesionTestedInputs = theInputs.Count;

                    int a = backPropAlg.bestLesion;
                    lesionInput = a;
                    lesionError = backPropAlg.lesionError[a] / theInputs[0].PointCount();
                    lesionAAM = backPropAlg.lesionAam[a];
                    lesionCorr = backPropAlg.lesionCorrelation[a];
                }

            }            

            this.SumSolQualityValLabel.Text = solutionQuality.ToString();// + "%";
            this.SumAamLabel.Text = aam.ToString();
            this.SumAvgErrLabel.Text = avgErr.ToString();

            this.SumLesionInputsCount.Text = lesionTestedInputs.ToString();
            this.SumLesionIterValLabel.Text = lesionIterVal.ToString();
            this.SumLesionTime.Text = lesionTime.ToString();
            this.SumLesionInput.Text = lesionInput.ToString();
            this.SumLesionError.Text = lesionError.ToString();
            this.SumLesionAAM.Text = lesionAAM.ToString();
            this.SumLesionCorr.Text = lesionCorr.ToString();
            this.SumTotTrainingCyclesValLabel.Text = backPropAlg.GetElapsedEpochs().ToString();
           
            //Layers = layers;
            Weights = backPropAlg.GetWeights();
            Biases = backPropAlg.GetBiases();
            
            trainingTime = (int)backPropAlg.backPropTrainingTime;

            TrainingCompleted();
        }


        public void EndGenAlg()
        {
            if (InvokeRequired)
            {
                //call BeginInvoke if we are not in the UI thread                
                BeginInvoke(new FinishTrainingDelegate(EndGenAlg), null);
                return;
            }

            double solutionQuality = 0;
            int epoch = theGenAlg.GetElapsedEpochs();            
            double aam = 0;
            double avgErr = 0;

            this.button3.Enabled = false;
            this.button7.Enabled = true;
            this.inputsToolStripMenuItem.Enabled = true;
            this.outputsToolStripMenuItem.Enabled = true;
            this.loadToolStripMenuItem.Enabled = true;
            networkInTraining = false;

            if (epoch > 0)
            {
                solutionQuality = theGenAlg.GetCorrelation(epoch - 1);                
                aam = theGenAlg.GetAAM(epoch - 1);
                avgErr = theGenAlg.getErrorofBestGenome(epoch - 1) / theInputs[0].PointCount();                

            }

            this.SumSolQualityValLabel.Text = solutionQuality.ToString();// + "%";
            this.SumAamLabel.Text = aam.ToString();
            this.SumAvgErrLabel.Text = avgErr.ToString();
            this.SumTotTrainingCyclesValLabel.Text = theGenAlg.GetElapsedEpochs().ToString();

            //set the weights for exporting
            Weights = theGenAlg.GetWeights();
            Biases = theGenAlg.GetBiases();

            trainingTime = (int)theGenAlg.genAlgTrainingTime;

            TrainingCompleted();
        }

        public void TrainingCompleted()
        {
            trainingCompleted = true;
            progressBar1.Value = 100;

            //enable dependent pages
            this.plottingToolStripMenuItem.Enabled = true;
            this.trainingSummaryToolStripMenuItem.Enabled = true;
            this.simulationToolStripMenuItem.Enabled = true;            

            //update all summary statistics and advance the active page to the summary page
            this.SumTrainingTimeValLabel.Text = trainingTime.ToString();
            this.SumNumInValLabel.Text = theInputs.Count.ToString();
            this.SumNumOutValLabel.Text = theOutputs.Count.ToString();
            //the number of hidden layers
            this.label17.Text = HiddenLayers.ToString();                        
            this.label18.Text = (HiddenNodes * HiddenLayers).ToString();

            //initialize training plots
            initializePlottingPage();

            //initialize simulation page
            panel5_Paint();
            TabControl.SelectTab(2);
        }

        public void BPErrorChanged()
        {
            if (InvokeRequired)
            {
                //call BeginInvoke if we are not in the UI thread                
                BeginInvoke(new ErrorPlotDelegate(BPErrorChanged), null);
                return;
            }

            Object[] point = new Object[2];
            int maxProg = 0;
            int epoch = -1;
            double err = -1;
            
            if (backPropAlg != null)
            {
                epoch = backPropAlg.GetElapsedEpochs();
                if (epoch > 0)
                {
                    if (backPropAlg.latestValidationError != -1)
                    {
                        err = backPropAlg.latestValidationError;
                    }
                    else
                    {
                        err = backPropAlg.GetRMSError(epoch);
                    }
                }
            }            

            //set plotting interval. 
            //Cap the error at 100000 so as not to overflow the plot
            if (epoch > 0 && epoch % PLOTTING_INTERVAL == 0 && err < 100000)
            {
                //add current error to the plot                                        
                point[0] = (int)epoch;
                point[1] = (double)err;
                currentError.Text = (err / theInputs[0].PointCount()).ToString();
                ds.Tables[0].Rows.Add(point);
                this.UpdateErrorPlot(ds);
                this.Update();
                errorPlot.Refresh();
                errorPlot.Update();

                if (backPropAlg.latestValidationError != -1)
                {
                    this.label23.Text = "Avg Error per validation set output";
                    if ((int)(100 * backPropAlg.convergenceParameter * theInputs[0].PointCount() / backPropAlg.latestValidationError) > maxProg)
                    {
                        maxProg = (int)(100 * backPropAlg.convergenceParameter * theInputs[0].PointCount() / backPropAlg.latestValidationError);
                        if (maxProg > 100)
                            maxProg = 95;
                    }
                }
                else
                {
                    this.label23.Text = "Avg Error per training set output";
                    if ((int)(100 * backPropAlg.convergenceParameter * theInputs[0].PointCount() / err) > maxProg)
                    {
                        maxProg = (int)(100 * backPropAlg.convergenceParameter * theInputs[0].PointCount() / err);
                        if (maxProg > 100)
                            maxProg = 95;
                    }
                }
                progressBar1.Value = maxProg;
            }
        }

        public void GAErrorChanged()
        {
            if (InvokeRequired)
            {
                //call BeginInvoke if we are not in the UI thread                
                BeginInvoke(new ErrorPlotDelegate(GAErrorChanged), null);
                return;
            }

            Object[] point = new Object[2];
            int maxProg = 0;
            int epoch = 0;
            double err = 0;
            
            if (theGenAlg != null)
            {
                epoch = theGenAlg.GetElapsedEpochs();
                if (epoch > 0)
                {
                    if (theGenAlg.latestValidationError != -1)
                    {
                        err = theGenAlg.latestValidationError;
                    }
                    else
                    {
                        err = theGenAlg.getErrorofBestGenome(epoch);
                    }
                }
            }
            //set plotting interval. 
            //Cap the error at 100000 so as not to overflow the plot
            if (epoch > 0 && epoch % PLOTTING_INTERVAL == 0 && err < 100000)
            {
                //add current error to the plot                                        
                point[0] = (int)epoch;
                point[1] = (double)err;
                currentError.Text = (err / theInputs[0].PointCount()).ToString();
                ds.Tables[0].Rows.Add(point);
                this.UpdateErrorPlot(ds);
                this.Update();
                errorPlot.Refresh();
                errorPlot.Update();

                if (theGenAlg.latestValidationError != -1)
                {
                    this.label23.Text = "Avg Error per validation set output";
                    if ((int)(100 * theGenAlg.convergenceParameter * theInputs[0].PointCount() / theGenAlg.latestValidationError) > maxProg)
                    {
                        maxProg = (int)(100 * theGenAlg.convergenceParameter * theInputs[0].PointCount() / theGenAlg.latestValidationError);
                        if (maxProg > 100)
                            maxProg = 95;
                    }
                }
                else
                {
                    this.label23.Text = "Avg Error per training set output";
                    if ((int)(100 * theGenAlg.convergenceParameter * theInputs[0].PointCount() / err) > maxProg)
                    {
                        maxProg = (int)(100 * theGenAlg.convergenceParameter * theInputs[0].PointCount() / err);
                        if (maxProg > 100)
                            maxProg = 95;
                    }
                }
                progressBar1.Value = maxProg;
            }
            
        }

        private void UpdateErrorPlot(DataSet ds)
        {
            System.Data.DataTable dt;
            errorPlot.Clear();
            dt = ds.Tables[0];
            NPlot.LinePlot pp = new LinePlot();
            pp.Color = Color.Red;
            pp.DataSource = dt;
            pp.AbscissaData = ds.Tables[0].Columns[0].ColumnName;
            pp.OrdinateData = ds.Tables[0].Columns[1].ColumnName;
            errorPlot.Add(pp);

            if (this.TrainingMethodComboBox.SelectedIndex == 1)
            {
                errorPlot.YAxis1.Label = "Total Error";
            }
            else
            {
                errorPlot.YAxis1.Label = "Total Error";
            }

            errorPlot.XAxis1.Label = "Training Epochs";

            //TODO Serge, stretch error plot
            //errorPlot.AddInteraction(new NPlot.Windows.NPlot.Windows.PlotSurface2D.Interactions.AxisDrag(false));
            //errorPlot.AddInteraction(new NPlot.Windows.NPlot.Windows.PlotSurface2D.Interactions.HorizontalDrag());
            //errorPlot.InteractionOccured += new NPlot.Windows.NPlot.Windows.PlotSurface2D.InteractionHandler(errorPlot_InteractionOccured);
            //errorPlot.PreRefresh += new NPlot.Windows.NPlot.Windows.PlotSurface2D.PreRefreshHandler(errorPlot_PreRefresh);
        }

        private void findBounds()
        {
            double lowerBound, upperBound;
            //////////////////////////////////////////////////////////////////////////
            //loop through data points and find good candidates for validation set
            //start by including the edges of the sample space in the training set             
            for (int a = 0; a < theInputs.Count; a++)
            {
                //create lists to hold the uppper and lower bounds of each input
                lowerBound = theInputs.ElementAt(a).LowerBounds;
                upperBound = theInputs.ElementAt(a).UpperBounds;
                inputLowerBoundsList.Add(lowerBound);
                inputUpperBoundsList.Add(upperBound);
            }
        }

        private bool splitInputs()
        {
            bool IsSplit = false;
            TrainingSet.Clear();
            ValidationSet.Clear();            
            Variable tempVarTS;
            Variable tempVarVS;
            int validationPoints, trainingPoints, totalDataPoints;
            int trainingPercent, validationPercent;
            int pointIndex = 0;
            double tempPoints;            
            List<double> tempValidationRows = new List<double>();
            //double lowerBound, upperBound;
            List<bool> bPointIncludedList = new List<bool>();

            trainingPercent = int.Parse(this.textBox8.Text);
            validationPercent = int.Parse(this.textBox9.Text);
            totalDataPoints = theInputs.ElementAt(0).PointCount();

            findBounds();

            if (trainingPercent + validationPercent == 100 && !inputsSplit)
            {
                tempPoints = ((double)(validationPercent) / 100) * totalDataPoints;
                validationPoints = (int)tempPoints;
                trainingPoints = totalDataPoints - validationPoints;
                //MessageBox.Show("validation points: " + validationPoints.ToString());

                for (int i = 0; i < theInputs.Count; i++)
                {
                    tempVarTS = new Variable();
                    tempVarTS.Type = "Independent";
                    tempVarTS.VariableName = theInputs.ElementAt(i).VariableName;
                    tempVarVS = new Variable();
                    tempVarVS.Type = "Independent";
                    tempVarVS.VariableName = theInputs.ElementAt(i).VariableName;
                    ValidationSet.Add(tempVarVS);
                    TrainingSet.Add(tempVarTS);
                }
                for (int a = 0; a < theOutputs.Count; a++)
                {
                    tempVarTS = new Variable();
                    tempVarTS.Type = "Dependent";
                    tempVarTS.VariableName = theOutputs.ElementAt(a).VariableName;
                    tempVarVS = new Variable();
                    tempVarVS.Type = "Dependent";
                    tempVarVS.VariableName = theOutputs.ElementAt(a).VariableName;
                    ValidationSet.Add(tempVarVS);
                    TrainingSet.Add(tempVarTS);
                }                

                //Add lower extremes of the sample space to the Training set
                for (int a = 0; a < theInputs.Count; a++)
                {
                    if (theInputs.ElementAt(a).GetPoints().Contains(inputLowerBoundsList.ElementAt(a)))
                    {
                        pointIndex = theInputs.ElementAt(a).GetPoints().IndexOf(inputLowerBoundsList.ElementAt(a), pointIndex);
                        bPointIncludedList.Clear();

                        if (pointIndex >= 0)
                        {
                            for (int x = 0; x < theInputs.Count; x++)
                            {
                                if (TrainingSet.ElementAt(x).GetPoints().Contains(theInputs.ElementAt(x).GetPoints().ElementAt(pointIndex)))
                                {
                                    bPointIncludedList.Add(true);
                                }
                                else
                                {
                                    bPointIncludedList.Add(false);
                                }
                            }

                            if (bPointIncludedList.Contains(false))
                            {
                                //add the point at position pointIndex to the set if it is a unique point
                                this.addPointToSet(TrainingSet, pointIndex);
                            }
                        }
                    }
                }

                //Add higher extremes from the sample space to the training set
                for (int a = 0; a < theInputs.Count; a++)
                {
                    if (theInputs.ElementAt(a).GetPoints().Contains(inputUpperBoundsList.ElementAt(a)))
                    {
                        pointIndex = theInputs.ElementAt(a).GetPoints().IndexOf(inputUpperBoundsList.ElementAt(a));
                        bPointIncludedList.Clear();

                        if (pointIndex >= 0)
                        {
                            for (int x = 0; x < theInputs.Count; x++)
                            {
                                if (TrainingSet.ElementAt(x).GetPoints().Contains(theInputs.ElementAt(x).GetPoints().ElementAt(pointIndex)))
                                {
                                    bPointIncludedList.Add(true);
                                }
                                else
                                {
                                    bPointIncludedList.Add(false);
                                }
                            }

                            if (bPointIncludedList.Contains(false))
                            {
                                //add the point at position pointIndex to the set if it is a unique point
                                this.addPointToSet(TrainingSet, pointIndex);
                            }
                        }
                    }
                }

                int pointsLeftToFill = validationPoints - ValidationSet.ElementAt(0).GetPoints().Count;
                int tempIndex;
                Random rand = new Random();


                //TODO: Serge, this is a cheap way of getting the rest of validation points
                //It is currently done randomly, a more intelligent way should be implemented...
                while (pointsLeftToFill > 0)
                {
                    tempIndex = rand.Next(0, theInputs.ElementAt(0).PointCount());
                    bPointIncludedList.Clear();

                    for (int a = 0; a < theInputs.Count; a++)
                    {
                        if (ValidationSet.ElementAt(a).GetPoints().Contains(theInputs.ElementAt(a).GetPoints().ElementAt(tempIndex)))
                        {
                            bPointIncludedList.Add(true);
                        }
                        else
                        {
                            bPointIncludedList.Add(false);
                        }
                    }
                    if (bPointIncludedList.Contains(false))
                    {
                        this.addPointToSet(ValidationSet, tempIndex);
                        pointsLeftToFill--;
                    }

                }

                pointsLeftToFill = theInputs.ElementAt(0).PointCount() - ValidationSet.ElementAt(0).PointCount() - TrainingSet.ElementAt(0).PointCount();

                //populate rest of the training set once the validation set has been created
                while (pointsLeftToFill > 0)
                {
                    tempIndex = rand.Next(0, theInputs.ElementAt(0).PointCount());
                    bPointIncludedList.Clear();

                    for (int a = 0; a < theInputs.Count; a++)
                    {
                        if (TrainingSet.ElementAt(a).GetPoints().Contains(theInputs.ElementAt(a).GetPoints().ElementAt(tempIndex)))
                        {
                            bPointIncludedList.Add(true);
                        }
                        else
                        {
                            bPointIncludedList.Add(false);
                        }
                    }
                    if (bPointIncludedList.Contains(false))
                    {
                        this.addPointToSet(TrainingSet, tempIndex);
                        //this.addPointToSet(TrainingSetInputsOnly, tempIndex);
                        pointsLeftToFill--;
                    }

                }

                //MessageBox.Show("ValidationSet count: " + ValidationSet.ElementAt(0).GetPoints().Count.ToString());
                inputsSplit = true;
                IsSplit = true;
            }
            else if (theInputs[0].PointCount() < 10 && theOutputs[0].PointCount() < 10)
            {
                MessageBox.Show("Warning! The data set is too small for a validation set. All points will be used to train the network.");
                IsSplit = false;
                inputsSplit = false;
            }
            else
            {
                MessageBox.Show("Warning! The input data cannot be split in this fashion. Check the training and validation set ratios. ");
                IsSplit = false;
                inputsSplit = false;
            }

            return IsSplit;
        }

        //Adds the point located at pointIndex from theInputs and theOutputs, to the list aSet
        private void addPointToSet(List<Variable> aSet, int pointIndex)
        {
            for (int b = 0; b < aSet.Count; b++)
            {
                //if the current variable is an input... add point value at pointIndex
                if (aSet.ElementAt(b).Type.Equals("Independent") && b < theInputs.Count)
                {
                    aSet.ElementAt(b).Add(theInputs.ElementAt(b).GetPoints().ElementAt(pointIndex));
                }
                else
                {
                    aSet.ElementAt(b).Add(theOutputs.ElementAt(b - theInputs.Count).GetPoints().ElementAt(pointIndex));
                }
            }
        }    

        #endregion

        #region Plotting Functions

        private void initializePlottingPage()
        {            
            Object[] point = new Object[3];
            int numberOfCases;
            double[] inputPoint;
            double[] outputPoint; //calculated during Fprop
            List<double[]> theCases = new List<double[]>();
            List<double[]> allPredictedOutputs = new List<double[]>();
            List<double[]> allMeasuredOutputs = new List<double[]>();
            plotList.Clear();           

            if (trainingCompleted)
            {
                //assign case numbers to input data
                numberOfCases = theInputs.ElementAt(0).PointCount();                

                for(int k = 0; k < theInputs.ElementAt(0).PointCount(); k++)
                {
                    inputPoint = new double[theInputs.Count];
                    for (int i = 0; i < theInputs.Count; i++)
                    {
                        inputPoint[i] = theInputs.ElementAt(i).GetPoints().ElementAt(k);
                    }
                    theCases.Add(inputPoint);
                }

                for (int j = 0; j < theOutputs.ElementAt(0).PointCount(); j++)
                {
                    outputPoint = new double[theOutputs.Count];
                    for (int k = 0; k < theOutputs.Count; k++)
                    {
                        outputPoint[k] = theOutputs[k].GetPoints()[j];
                    }
                    allMeasuredOutputs.Add(outputPoint);
                }

                //run cases through Fprop
                outputPoint = new double[theOutputs.Count];
                allPredictedOutputs.Clear();
                for (int i = 0; i < numberOfCases; i++)
                {
                    /* was used to circumvent scaling
                    for (int j = 0; j < theOutputs.Count; j++)
                        outputPoint[j] = backPropAlg.nnOutputs[i, j];
                    
                    allPredictedOutputs.Add((double[]) outputPoint.Clone());
                    */
                    if (TrainingMethodComboBox.SelectedIndex == 0)
                    {
                        outputPoint = backPropAlg.Fprop(theCases.ElementAt(i));
                        allPredictedOutputs.Add(outputPoint);
                    }
                    else
                    {
                        outputPoint = theGenAlg.Fprop(theCases.ElementAt(i));
                        allPredictedOutputs.Add(outputPoint);
                    }
                }

                //create plots
                for (int i = 0; i < outputPoint.Length; i++)
                {
                    NPlot.Windows.PlotSurface2D aPlot = new NPlot.Windows.PlotSurface2D();
                    NPlot.Legend leg = new NPlot.Legend();
                    leg.AttachTo(NPlot.PlotSurface2D.XAxisPosition.Top, NPlot.PlotSurface2D.YAxisPosition.Right);
                    leg.VerticalEdgePlacement = NPlot.Legend.Placement.Outside; 
                    leg.HorizontalEdgePlacement = NPlot.Legend.Placement.Inside;
                    leg.BorderStyle = NPlot.LegendBase.BorderType.Line;                    
                    
                    aPlot.Clear();
                    aPlot.AutoScaleAutoGeneratedAxes = false;
                    aPlot.AutoScaleTitle = false;                    
                    aPlot.PlotBackColor = System.Drawing.SystemColors.ControlLightLight;
                    aPlot.Legend = leg;                    
                    aPlot.Name = theOutputList[i] + " Plot";
                    aPlot.RightMenu = null;
                    aPlot.ShowCoordinates = false;
                    aPlot.Location = new System.Drawing.Point(10, 20);
                    aPlot.Height = this.panel4.Height - 25;
                    aPlot.Width = this.panel4.Width - 20;
                    aPlot.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;                    
                    aPlot.Title = "Measured vs Predicted " + theOutputList[i];
                    aPlot.TitleFont = new System.Drawing.Font("Arial", 14F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Pixel);                    
                    
                    plotList.Add(aPlot);

                    DataSet ds = new DataSet(theOutputList.ElementAt(i));

                    ds.Tables.Add();
                    ds.Tables[0].Columns.Add();
                    ds.Tables[0].Columns[0].DataType = System.Type.GetType("System.Int32");
                    ds.Tables[0].Columns[0].ColumnName = "Case";
                    ds.Tables[0].Columns.Add();
                    ds.Tables[0].Columns[1].DataType = System.Type.GetType("System.Double");
                    ds.Tables[0].Columns[1].ColumnName = "Measured " + theOutputList[i];
                    ds.Tables[0].Columns.Add();
                    ds.Tables[0].Columns[2].DataType = System.Type.GetType("System.Double");
                    ds.Tables[0].Columns[2].ColumnName = "Predicted " + theOutputList[i];

                    //populate the plots
                    for (int x = 0; x < numberOfCases; x++)
                    {
                        point[0] = x;
                        point[1] = allMeasuredOutputs.ElementAt(x).ElementAt(i);
                        point[2] = allPredictedOutputs.ElementAt(x).ElementAt(i);
                        ds.Tables[0].Rows.Add(point);
                    }

                    //aPlot.YAxis1.LabelOffsetAbsolute = true;
                    //aPlot.YAxis1.LabelOffset = 40;                    
                    aPlot.Padding = 1;
                    aPlot.AddAxesConstraint(new AxesConstraint.AxisPosition(PlotSurface2D.YAxisPosition.Left, 60));                   

                    System.Data.DataTable dt;                    
                    dt = ds.Tables[0];
                    NPlot.PointPlot measuredPoints = new PointPlot();
                    NPlot.PointPlot predictedPoints = new PointPlot();
                    
                    measuredPoints.Marker.Color = Color.Blue;
                    measuredPoints.DataSource = dt;
                    measuredPoints.AbscissaData = ds.Tables[0].Columns[0].ColumnName;
                    measuredPoints.OrdinateData = ds.Tables[0].Columns[1].ColumnName;
                    measuredPoints.Label = "Measured Outputs";
                    predictedPoints.Marker.Color = Color.Red;
                    predictedPoints.DataSource = dt;
                    predictedPoints.AbscissaData = ds.Tables[0].Columns[0].ColumnName;
                    predictedPoints.OrdinateData = ds.Tables[0].Columns[2].ColumnName;
                    predictedPoints.Label = "Predicted Outputs";

                    aPlot.Add(measuredPoints);
                    aPlot.Add(predictedPoints);
                    
                    this.Refresh();
                    this.Update();
                }

                for (int a = 0; a < theOutputList.Count; a++)
                {
                    comboBox4.Items.Add(theOutputList[a]);
                }

                this.panel4.Controls.Add(plotList[0]);
                comboBox4.SelectedIndex = 0;

                /*int b = panel4.Controls.Count;
                while (b >= 0)
                {
                    this.panel4.Controls.RemoveAt(b - 1);
                    b--;
                }*/                
            }
        }

        #endregion

        #region Simulation Page Functions

        private void ExportWeights_Click(object sender, EventArgs e)
        {
            saveFileDialog1.ShowDialog();
        }

        private void saveFileDialog1_FileOk(object sender, CancelEventArgs e)
        {
            StreamWriter WeightFile = new StreamWriter(saveFileDialog1.FileName);
            WeightFile.WriteLine(backPropAlg.scaleMax);
            WeightFile.WriteLine(backPropAlg.scaleMin);
            WeightFile.WriteLine(ActivationFunction);
            WeightFile.WriteLine(Layers.Length);
            
            for(int x=0; x<Layers.Length;x++)
            {
                WeightFile.WriteLine(Layers[x]);
            }
            for (int c = 0; c < Layers[0]; c++)
            {
                WeightFile.WriteLine(inputLowerBoundsList[c]);
                WeightFile.WriteLine(inputUpperBoundsList[c]);
            }
            for (int i = 0; i < Weights.Length; i++)
            {
                //WeightFile.WriteLine("Layer "+i);            
                for (int j = 0; j < Weights[i].Length; j++)
                {
                    for (int k = 0; k < Weights[i][j].Length; k++)
                    {
                        WeightFile.Write(Weights[i][j][k] + ",");
                    }
                    WeightFile.WriteLine();
                }
            }
            //WeightFile.WriteLine("Biases");
            for (int a = 0; a < Biases.Length; a++)
            {
                for (int b = 0; b < Biases[a].Length; b++)
                {
                    WeightFile.Write(Biases[a][b] + ",");
                }
                WeightFile.WriteLine();
            }
            WeightFile.Close();
        }

        private void openFileDialog2_FileOk(object sender, CancelEventArgs e)
        {
            StreamReader WeightFile = new StreamReader(openFileDialog2.FileName);
            string line;
            line = WeightFile.ReadLine();
            double scaleMax = double.Parse(line);
            line = WeightFile.ReadLine();
            double scaleMin = double.Parse(line);
            line = WeightFile.ReadLine();
            
            ActivationFunction = line[0];

            
            line = WeightFile.ReadLine();
            Layers = new int[System.Convert.ToInt32(line)];
            for (int x = 0; x < Layers.Length; x++)
            {
                line = WeightFile.ReadLine();
                Layers[x] = System.Convert.ToInt32(line);
            }
            for (int c = 0; c < Layers[0]; c++)
            {
                line = WeightFile.ReadLine();
                inputLowerBoundsList.Add(double.Parse(line));
                line = WeightFile.ReadLine();
                inputUpperBoundsList.Add(double.Parse(line));
            }

            backPropAlg = new backprop(Layers);
            backPropAlg.nnFunction = ActivationFunction;
            backPropAlg.SetLayers(Layers);
            backPropAlg.scaleMax = scaleMax;
            backPropAlg.scaleMin = scaleMin;
            //set up weight and bias arrays
            Weights= new double[Layers.Length-1][][];
            Biases = new double[Layers.Length - 1][];
            for(int i = 0; i < Weights.Length; i++)
            {
                Weights[i] = new double[Layers[i]][]; 
                Biases[i] = new double[Layers[i+1]];
                for (int j = 0; j < Layers[i]; j++)
                {
                    Weights[i][j] = new double[Layers[i + 1]];

                }

            }

            //read in weight values
            for (int i = 0; i < Weights.Length; i++)
            {
                for (int j = 0; j < Weights[i].Length; j++)
                {
                    line = WeightFile.ReadLine();
                    string[] Wentries = line.Split(',');
                    for (int k = 0; k < Weights[i][j].Length; k++)
                    {
                        Weights[i][j][k] = System.Convert.ToDouble(Wentries[k]);
                        backPropAlg.SetWeights( Weights);
                    }
                    
                }
            }
            //read in Biases
            for (int a = 0; a < Biases.Length; a++)
            {
                line = WeightFile.ReadLine();
                string[] Bentries = line.Split(',');
                    for(int b=0; b<Biases[a].Length;b++)
                    {
                       Biases[a][b]= System.Convert.ToDouble(Bentries[b]);
                       backPropAlg.SetBiases(Biases);
                    }
            }
            trainingCompleted = true;
            button7.Enabled = true;
            importedWeights = true;
            panel5_Paint(); 
        }
        
        private void panel5_Paint()
        {
            //initialize the bounds in case they haven't been
            this.findBounds();

            //in case backProp is not initialized...
            if (backPropAlg == null)
            {
                backPropAlg = new backprop(Layers);
                backPropAlg.SetBiases(this.Biases);
                backPropAlg.SetWeights(this.Weights);
                backPropAlg.nnFunction = this.ActivationFunction;
                backPropAlg.scaleMax = theGenAlg.scaleMax;
                backPropAlg.scaleMin = theGenAlg.scaleMin;
            }

            for (int i = 0; i < Layers[0]; i++)            
            {
                SimulationControl simControl = new SimulationControl();
                simControl.Max=(int)inputUpperBoundsList[i] +1;
                simControl.Min = (int)inputLowerBoundsList[i];
                simControl.Location = new System.Drawing.Point(3,(i * 90));
                try { simControl.Label = theInputList[i]; }
                catch { simControl.Label = "Input "+i; }
                simControl.Value = inputLowerBoundsList[i];
                simControl.ValueChanged += new System.EventHandler(this.button5_Click);
                panel5.Controls.Add(simControl);                
            }
            for (int j = 0; j < Layers[Layers.Length-1]; j++)
            {
                Label outputLabel = new Label();
                try { outputLabel.Text = theOutputList[j] + ":"; }
                catch { outputLabel.Text = "Output " + j; }
                outputLabel.Location= new System.Drawing.Point(3,(j * 30));
                panel6.Controls.Add(outputLabel);
            }
            
        }
        private void button5_Click(object sender, EventArgs e)
        {
            double[] simInputs = new double[Layers[0]];
            double[] simOutputs;
            for (int i = 0; i < Layers[0]; i++)
            {
                SimulationControl temp = (SimulationControl) panel5.Controls[i];
                simInputs[i] =temp.Value;
                
            }

            if (TrainingMethodComboBox.SelectedIndex == 0)
            {
                simOutputs = backPropAlg.Fprop(simInputs);
            }
            else
            {
                simOutputs = theGenAlg.Fprop(simInputs);
            }
            panel6.Controls.Clear();
            for (int j = 0; j < Layers[Layers.Length-1]; j++)
            {
                Label outputLabel = new Label();
                try { outputLabel.Text = theOutputList[j] + ":"; }
                catch { outputLabel.Text = "Output " + j; }
                outputLabel.Location = new System.Drawing.Point(3, (j * 30));

                panel6.Controls.Add(outputLabel);
                Label outputLabel2 = new Label();
                outputLabel2.Text = simOutputs[j].ToString();
                outputLabel2.Location = new System.Drawing.Point(100, (j * 30));

                panel6.Controls.Add(outputLabel2);                
            }
        }
        
        #endregion     

        #region Misc Event Handlers

        private void tabPage1_Click(object sender, EventArgs e)
        {
            tabPage1.Show();
        }

        //Next button clicked
        //Verify that the inputs and outputs are valid
        private void tabPage2_Click(object sender, EventArgs e)
        {
            if (numericUpDown1.Value > 0 && numericUpDown2.Value > 0)
            {
                this.validateInputData();
                this.storeInputData();
                if (this.inputValidated)
                {
                    //splitInputs();
                    TabControl.SelectTab(1);

                }
            }
            else
            {
                MessageBox.Show("No inputs/outputs found! Please check the input data");
            }

        }

        //Load the Plotting Page
        private void SumPlottingButton_Click(object sender, EventArgs e)
        {
            if (trainingCompleted)
            {
                this.TabControl.SelectTab(3);
            }
        }


        //update the plot being displayed on the Plotting page
        private void comboBox4_SelectedIndexChanged(object sender, EventArgs e)
        {
            int i = panel4.Controls.Count;
            while (i > 0)
            {
                this.panel4.Controls.RemoveAt(i - 1);
                i--;
            }
            if (panel4.Controls.Count == 0)
            {
                panel4.Controls.Add(plotList.ElementAt(this.comboBox4.SelectedIndex));
            }
        }

        //navigate to simulation page from plotting page.
        private void PlotToSimButton_Click(object sender, EventArgs e)
        {
            if (trainingCompleted)
            {
                this.TabControl.SelectTab(4);
            }
        }

        private void button2_Click_1(object sender, EventArgs e)
        {
            if (comboBox1.SelectedIndex == 0)
            {
            }
        }

        private void dataGridView2_UserDeletingRow(object sender, DataGridViewRowCancelEventArgs e)
        {
            int currentIndex;
            currentIndex = e.Row.Index;
            this.dataGridView1.Rows.RemoveAt(currentIndex);
        }
        private void dataGridView1_UserDeletingRow(object sender, DataGridViewRowCancelEventArgs e)
        {
            int currentIndex;
            currentIndex = e.Row.Index;
            this.dataGridView2.Rows.RemoveAt(currentIndex);
        }

        //back button, config network page
        private void backButton_Click(object sender, EventArgs e)
        {
            if (!networkInTraining)
            {
                TabControl.SelectTab(0);
            }
        }

        private void inputsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            InputParamsDialogBox.Show();
        }

        private void outputsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.OutputsDialogBox.Show();
        }

        /*private void numericUpDown4_ValueChanged(object sender, EventArgs e)
        {

        }*/

        public List<Variable> getInputs()
        {
            return this.theInputs;
        }

        public List<Variable> getOutputs()
        {
            return this.theOutputs;
        }

        //The enable lesioning check box event handler
        private void checkBox1_CheckedChanged(object sender, EventArgs e)
        {
            IsLesioningEnabled = this.checkBox1.Checked;
        }

        //Cancel Button, Configure Network page
        private void button3_Click(object sender, EventArgs e)
        {
            stopTraining = true;
            networkInTraining = false;
            button3.Enabled = false;

            if (bpThread != null)
            {
                bpThread.Abort();
                if (backPropAlg != null)
                {
                    
                    backPropAlg.abortTraining();
                    Weights = backPropAlg.GetWeights();
                    Biases = backPropAlg.GetBiases();
                }
            }
            else if (genThread != null)
            {
                genThread.Abort();
                if (theGenAlg != null)
                {                    
                    theGenAlg.abortTraining();
                    Weights = theGenAlg.GetWeights();
                    Biases = theGenAlg.GetBiases();
                }
            }
        }

        private void TrainingMethodComboBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            //gradient descent
            if (TrainingMethodComboBox.SelectedIndex == 0)
            {
                groupBox10.Hide();
                this.BufferParameterGroupBox.Visible = true;
                groupBox9 = this.BufferParameterGroupBox;
                groupBox9.Visible = true;
                groupBox9.Show();
                groupBox9.Select();

                //read params from back prop config params
                HiddenNodes = int.Parse(this.textBox10.Text);
                HiddenLayers = (int)this.numericUpDown4.Value;
            }
            //gen alg training selected
            else if (TrainingMethodComboBox.SelectedIndex == 1)
            {
                groupBox10.Visible = true;
                this.BufferParameterGroupBox.Visible = false;
                groupBox9 = groupBox10;
                groupBox9.Visible = true;
                groupBox9.Show();
                groupBox9.Select();

                //read params from gen alg config params
                HiddenNodes = int.Parse(this.textBox11.Text);
                HiddenLayers = (int)this.numericUpDown5.Value;
            }
        }

        //return to summary page from plotting page
        private void PlotToSummaryButton_Click(object sender, EventArgs e)
        {
            this.TabControl.SelectTab(2);
        }
        //return to Plotting page from simulation page
        private void SimToPlotButton_Click(object sender, EventArgs e)
        {
            this.TabControl.SelectTab(3);
        }

        #endregion       

        private void button4_Click(object sender, EventArgs e)
        {
            openFileDialog2.ShowDialog();
        }        
    }
}
